package com.lixin.web.webSocket.impl;

import com.lixin.model.request.AckRequest;
import com.lixin.model.response.Response;
import com.lixin.model.response.UnreadMessagesResponse;
import com.lixin.redis.ListRedisUtil;
import com.lixin.redis.RedisKey;
import com.lixin.redis.StringRedisUtil;
import com.lixin.web.netty.NettyUtil;
import com.lixin.web.webSocket.MessageManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;

/**
 * Description: 管理系统中的所有消息 整合 修改及分发
 * Copyright:   Copyright (c)2023
 * Company:     sci
 *
 * @author: 张李鑫
 * @version: 1.0
 * Create at:   2023-08-12 01:15:12
 * <p>
 * Modification History:
 * Date         Author      Version     Description
 * ------------------------------------------------------------------
 * 2023-08-12     张李鑫                     1.0         1.0 Version
 */
@Service("message")
public class MessageManagerImpl implements MessageManager {

    private static final Integer DEFAULT_PAGE_SIZE = 100;

    @Autowired
    private ListRedisUtil listRedisUtil;

    @Autowired
    private StringRedisUtil stringRedisUtil;


    /**
     * 获取用户的未读消息
     *
     * @return
     */
    @Override
    public Response<UnreadMessagesResponse> getUnreadMessagesForUser() {
        //其实这里应该查询缓存。在查询数据库读取 因为有可能出现缓存失效的场景 todo
        long messageCount = getUnreadMessageCount();
        if (messageCount == 0) {
            return Response.success();
        }
        //考虑如果群聊消息很多可能存在消息积压的情况
        //如果存储长度小于默认分页 直接返回
        List<Object> res = getUnreadMessages(messageCount);
        //存储此次行为 如果客户端成功处理数据应该发送ack
        UnreadMessagesResponse unreadMessagesResponse = new UnreadMessagesResponse();
        unreadMessagesResponse.setAckCode(generateAckCodeAndStoreAckInfo(messageCount));
        unreadMessagesResponse.setData(res);
        unreadMessagesResponse.setHasNest(messageCount > DEFAULT_PAGE_SIZE);
        return Response.success(unreadMessagesResponse);
    }

    private String generateAckCodeAndStoreAckInfo(long messageCount) {
        String ackCode = UUID.randomUUID().toString();
        stringRedisUtil.set(
                RedisKey.getKey(
                        RedisKey.USER_NOTIFY,
                        NettyUtil.getUserId(),
                        ackCode
                ),
                Long.toString(messageCount)
        );
        return ackCode;
    }

    /**
     * 分页获取
     *
     * @param messageCount
     * @return
     */
    private List<Object> getUnreadMessages(long messageCount) {
        return listRedisUtil.lRange(
                RedisKey.getKey(
                        RedisKey.USER_NOTIFY,
                        NettyUtil.getUserId()
                ),
                messageCount > DEFAULT_PAGE_SIZE ? -DEFAULT_PAGE_SIZE : -messageCount,
                -1
        );
    }


    private long getUnreadMessageCount() {
        return listRedisUtil.lLen(RedisKey.getKey(RedisKey.USER_NOTIFY, NettyUtil.getUserId()));
    }


    /**
     * 去删除当前请求已经响应的redis数据 模拟ack
     *
     * @return
     */
    @Override
    public Response<Object> ack(AckRequest ackRequest) {
        String pageSize = stringRedisUtil.get(RedisKey.getKey(RedisKey.USER_NOTIFY, NettyUtil.getUserId(), ackRequest.getAckCode()));
        listRedisUtil.lTrim(RedisKey.getKey(RedisKey.USER_NOTIFY, NettyUtil.getUserId()), 0, -1 * (Integer.parseInt(pageSize) + 1));//从后删 redis的规则是保留从0-n的数字所以要多加一个索引
        return Response.success();
    }

}
